package randomtest.weightrandom;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class WeightRandomTest {
  private static Map<Double, String> weightMapping = new HashMap<>();

  static {
    weightMapping.put(20D, "B");
    weightMapping.put(40D, "D");
    weightMapping.put(30D, "A");
    weightMapping.put(50D, "C");


//    weightMapping.put(10D, "E");

  }

  public static void main(String[] args) {
    int c = 0;
    int a = 0;
    int b = 0;
    int d = 0;
    int e = 0;
    for (int i = 0; i < 2000000; i++) {
      String str = WeightRandomUtil.getWeightRandom(weightMapping);
      if ("A".equals(str)) {
        a++;
      } else if ("B".equals(str)) {
        b++;
      } else if ("C".equals(str)) {
        c++;
      } else if ("D".equals(str)) {
        d++;
      }
// else if ("E".equals(str)) {
//        e++;
//      }
    }

    System.out.println(c / 2000000d);
    System.out.println(d / 2000000d);
    System.out.println(a / 2000000d);
    System.out.println(b / 2000000d);
//    System.out.println(e / 2000000d);
  }
}

class WeightRandomUtil {

  /***
   * 计算权重总和
   *
   * @param weightArrays
   * @return
   * @author zhangwei<wei.zw   @   corp.netease.com>
   */
  private static double weightSum(Set<Double> weights) {
    double weightSum = 0;
    for (double weightValue : weights) {
      weightSum += weightValue;
    }
    return weightSum;
  }

  /***
   *
   *
   * @param weightArrays
   *            权重数组
   * @return 返回数据
   * @author zhangwei<wei.zw   @   corp.netease.com>
   * @param <T>
   */
  public static <T> T getWeightRandom(Map<Double, T> weightValueMapping) {
    double weightSum = weightSum(weightValueMapping.keySet());
    double stepWeightSum = 0;
    List<Double> list = new ArrayList<>(weightValueMapping.keySet());
//    Collections.sort(list, new Comparator<Double>() {
//
//      @Override
//      public int compare(Double o1, Double o2) {
//        return (int) (o2 - o1);
//      }
//
//    });
//    Collections.sort(list, (o1, o2) -> {
//      return (int) (o1 - o2);
//    });
    double r = Math.random();
    for (double weight : list) {
      // 计算权重值
      stepWeightSum += weight;
      // 如果随机数落在了权重区间则返回索引值
      if (r <= stepWeightSum / weightSum) {
        return weightValueMapping.get(weight);
      }
    }
    return null;
  }

  public static <T> T getWeightRandom2(List<T> lists, List<Double> weightsList,double weightSum) {
    double stepWeightSum = 0;
    double r = Math.random();
    for(int i=0;i<weightsList.size();i++){
      stepWeightSum += weightsList.get(i);
      if (r <= stepWeightSum / weightSum) {
        return lists.get(i);
      }
    }
    return null;
  }

}  
